package org.example;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;

import java.lang.reflect.Method;

/**
 * 演示: 通过 javassist程序生成一个简单的class文件, 仅包含无参无返回值的方法.
 * 并调用其中的方法.整个工程中并没有手写 Programmer类.
 *
 * 注意:只有运行了该类的main方法,才会在target/classes目录下,生成com.scy.example.Duck.class文件
 */
public class AppGenNewSimpleCzBySsist {

    public static void main(String[] args) throws Exception {

        CtClass ctClass = genClass();
        invokeMethod(ctClass,"code");
    }

    public static CtClass genClass()throws Exception {

        //设置将生成的class放置的目录
        String postFix = "target/genSimpleCzByJs";
        String genClassDir = System.getProperty("user.dir") + "/javassistTest/" + postFix;

        ClassPool pool = ClassPool.getDefault();
        //创建Programmer类
        CtClass cc = pool.makeClass("com.javassist.example.Programmer");
        //定义code方法
        CtMethod method = CtNewMethod.make("public void code(){}", cc);
        //插入方法代码
        method.insertBefore("System.out.println(\"I'm a Programmer,Just Coding.....\");");
        cc.addMethod(method);

        //可以将生成的class信息写入文件中,用于查看
        cc.writeFile(genClassDir);
        System.out.println("将生成的class信息写入"+ postFix
                +"目录中,仅供查看.也可以不进行这个操作,后续依然可以调用");

        return cc;
    }

    public static void invokeMethod(CtClass ctClass,String methodName)throws Exception {
        //将class信息转到一个Class对象中
        Class<?> aClass = ctClass.toClass();

        System.out.println(aClass.getName());// com.javassist.example.Programmer
        System.out.println(aClass.getPackage());//注意获取的包名为 null


        Object o = aClass.newInstance();
        Method codeMethod = aClass.getDeclaredMethod(methodName);
        System.out.println("调用生成的class对象中的方法.");
        codeMethod.invoke(o);
    }
}
